package com.ns.sbs.oauth.acc.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ns.core.annotations.ReqLog;
import com.ns.core.bo.IdsBO;
import com.ns.core.utils.StpUtil;
import com.ns.core.utils.sg.ResultError;
import com.ns.core.utils.sg.ResultOk;
import com.ns.sbs.oauth.acc.bo.AccBO;
import com.ns.sbs.oauth.acc.bo.AccPageBO;
import com.ns.sbs.oauth.acc.dto.AccPageDto;
import com.ns.sbs.oauth.acc.entry.Acc2Server;
import com.ns.sbs.oauth.acc.entry.Account;
import com.ns.sbs.oauth.acc.service.IAcc2ServerService;
import com.ns.sbs.oauth.acc.service.IAccountService;
import com.ns.sbs.oauth.acc.vo.AccCompleteVO;
import com.ns.sbs.oauth.acc.vo.AccVO;
import com.ns.sbs.oauth.acc4auth.service.IAccPasswordService;
import com.ns.sbs.oauth.role.service.IRoleService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.Objects;

/**
 * 系统管理业务相关操作
 *
 * @author lw
 */
@RestController
@RequestMapping("/sso/acc/")
@RequiredArgsConstructor
@CrossOrigin
public class SsoAccController {

    private final IAccountService accountService;

    private final IAccPasswordService accPasswordService;

    private final IRoleService roleService;

    private final IAcc2ServerService acc2ServerService;

    /**
     * 增
     *
     * @param bo 参数
     *           <p>
     *           逻辑：检查当前手机号是否存在
     *           1. 存在时：判断是否在同一租户
     *           1.1 同一租户：
     *           1.1.1 判断是否存在该服务
     *           1.1.1.1 存在 错误提示
     *           1.1.1.2 不存在 弹出是否绑定
     *           <p>
     *           1.2 不同租户：错误提示
     *           2. 不存在时，直接新增并绑定服务
     */
    @PostMapping("add")
    @ReqLog(module = "管理员模块", name = "增")
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public ResultOk add(@RequestBody AccBO bo) {
        // 当前手机号获取用户
        AccCompleteVO acc = accountService.getAccByPhone(bo.getPhone());
        if (Objects.nonNull(acc)) {
            // 判断同租户
            if (Objects.equals(acc.getRid(), StpUtil.getRid())) {
                // 判断服务是否绑定
                Long sid = StpUtil.getSid();
                Acc2Server exist = acc2ServerService.getByAccAndSid(acc.getId(), sid);
                if (Objects.isNull(exist)) {
                    return ResultOk.getSuccess(ResultOk.CODE_WAITE_CONFIRM, acc.getId());
                } else {
                    throw new ResultError("该手机号" + bo.getPhone() + "已被" + bo.getName() + "占用！");
                }
            } else {
                throw new ResultError("该手机号" + bo.getPhone() + "已被占用！");
            }
        } else {
            Account account = new Account();
            BeanUtils.copyProperties(bo, account);
            account.setSort(accountService.count() + 1);
            if (accountService.save(account)) {
                // 更改密码（md5与明文）
                accPasswordService.updatePassword(account.getId(), account.getPassword());
            }
            // 仅新增操作：保存账户根服务关系
            if (Objects.nonNull(bo.getRoleId())) {
                this.acc2Server(account.getId(), StpUtil.getSid(), bo.getRoleId());
            }
            return ResultOk.getSuccessData(account.getId());
        }
    }


    /**
     * 改
     *
     * @param bo 参数
     */
    @PostMapping("update")
    @ReqLog(module = "管理员模块", name = "改信息")
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public ResultOk updateAll(@RequestBody AccBO bo) {
        Account account = new Account();
        BeanUtils.copyProperties(bo, account);
        // 当前手机号获取用户
        AccCompleteVO acc = accountService.getAccByPhone(bo.getPhone());
        if (Objects.nonNull(acc)) {
            if (Objects.equals(acc.getId(), bo.getId())) {
                accountService.updateById(account);
            } else {
                throw new ResultError(String.format("该手机号%s已被使用！", account.getPhone()));
            }
        } else {
            accountService.updateById(account);
        }
        // 更新账户服务菜单关联表
        acc2ServerService.delByAccIdAndSid(account.getId(), StpUtil.getSid());
        this.acc2Server(account.getId(), StpUtil.getSid(), bo.getRoleId());

        return ResultOk.getSuccessData(account.getId());
    }

    /**
     * 删
     *
     * @param id 参数
     */
    @GetMapping("delete")
    @ReqLog(module = "管理员模块", name = "删")
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public ResultOk delete(Long id) {
        // 不能自己删除自己
        if (Objects.equals(StpUtil.getLoginUserId(), id)) {
            return ResultOk.getError("不能自己删除自己");
        }
        boolean flag = accountService.removeById(id);
        if (flag) {
            acc2ServerService.delByAccId(id);
        }
        return ResultOk.getByBoolean(flag);
    }

    /**
     * 删 - 根据id列表
     */
    @PostMapping("deleteByIds")
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    @ReqLog(module = "管理员模块", name = "批量删")
    public ResultOk deleteByIds(@RequestBody IdsBO bo) {
        // 不能自己删除自己
        if (bo.getIds().contains(StpUtil.getLoginUserId())) {
            return ResultOk.getError("不能自己删除自己");
        }
        // 开始删除
        int i = accountService.deleteByIds(bo.getIds());
        acc2ServerService.delByAccIds(bo.getIds());
        return ResultOk.getByLine(i);
    }

    /**
     * 查
     *
     * @param id 参数
     */
    @GetMapping("getById")
    @ReqLog(module = "管理员模块", name = "查")
    public ResultOk getById(Long id) {
        if (Objects.isNull(id)) {
            id = StpUtil.getLoginUserId();
        }
        return ResultOk.getSuccessData(accountService.getAccById(id, StpUtil.getSid()));
    }

    /**
     * 查 - 集合
     */
    @PostMapping("getList")
    @ReqLog(module = "管理员模块", name = "集合")
    public ResultOk getList(@RequestBody AccPageBO bo) {
        AccPageDto dto = new AccPageDto();
        BeanUtils.copyProperties(bo, dto);
        Page<AccVO> page = accountService.getList(dto);
        return ResultOk.getPageData(page.getTotal(), page.getRecords());
    }

    /**
     * 改密码
     *
     * @param id       参数
     * @param password 参数
     */
    @GetMapping("updatePassword")
    @ReqLog(module = "管理员模块", name = "改密码")
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public ResultOk updatePassword(long id, String password) {
        return ResultOk.getByLine(accPasswordService.updatePassword(id, password));
    }


    /**
     * 改头像
     *
     * @param id     参数
     * @param avatar 参数
     */
    @GetMapping("updateAvatar")
    @ReqLog(module = "管理员模块", name = "改头像")
    public ResultOk updateAvatar(Long id, String avatar) {
        // 修改状态
        Account account = new Account();
        account.setId(id);
        account.setAvatar(avatar);
        account.setModifier(StpUtil.getLoginUserId());
        return ResultOk.getByBoolean(accountService.updateById(account));
    }

    /**
     * 改状态
     *
     * @param id     参数
     * @param status 参数
     */
    @GetMapping("updateStatus")
    @ReqLog(module = "管理员模块", name = "改状态")
    public ResultOk updateStatus(Long id, int status) {
        // 验证当前处理人员角色等级
        if (roleService.hasPermission(StpUtil.getLoginUserId(), id)) {
            return ResultOk.getError("抱歉，您的角色权限只能操作低于您权限的用户！");
        }
        // 修改状态
        Account account = new Account();
        account.setId(id);
        account.setStatus(status);
        account.setModifier(StpUtil.getLoginUserId());
        accountService.updateById(account);
        // 如果是禁用，就将其强制注销
        if (status == 0) {
            StpUtil.logout(id);
        }
        return ResultOk.getSuccess();
    }

    /**
     * 改角色
     *
     * @param id     参数
     * @param roleId 参数
     */
    @GetMapping("updateRole")
    @ReqLog(module = "管理员模块", name = "改角色")
    public ResultOk updateRole(Long id, Long roleId) {
        // 改角色
        Acc2Server acc2Server = new Acc2Server();
        acc2Server.setRoleId(roleId);
        acc2Server.setSid(StpUtil.getSid());
        acc2Server.setAccId(id);
        int line = acc2ServerService.updateRole(acc2Server);
        ResultError.throwByLine(line, "角色变更失败！");
        return ResultOk.getSuccess();
    }


    /**
     * 返回当前 account 信息
     */
    @GetMapping("getByCurr")
    @ReqLog(module = "管理员模块", name = "当前用户")
    public ResultOk getByCurr() {
        return ResultOk.getSuccessData(StpUtil.getCurUser());
    }


    /**
     * 当前 account 修改自己信息
     *
     * @param obj 参数
     */
    @PostMapping("updateInfo")
    @ReqLog(module = "管理员模块", name = "改信息")
    public ResultOk updateInfo(@RequestBody Account obj) {
        obj.setId(StpUtil.getLoginUserId());
        return ResultOk.getByBoolean(accountService.updateById(obj));
    }

    /**
     * 绑定服务
     *
     * @param accId  账户id
     * @param sid    服务id
     * @param roleId 角色ID参数
     */
    @GetMapping("acc2Server")
    @ReqLog(module = "管理员模块", name = "绑定服务")
    public ResultOk acc2Server(Long accId, Long sid, Long roleId) {
        Acc2Server acc2Server = new Acc2Server();
        acc2Server.setAccId(accId);
        acc2Server.setSid(Objects.isNull(sid) ? StpUtil.getSid() : sid);
        acc2Server.setRoleId(roleId);
        return ResultOk.getByBoolean(acc2ServerService.save(acc2Server));
    }
}
